using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using FiltronASP.Areas.Admin.ViewModels;
using FiltronASP.Helpers.ErrorHandling;
using FiltronASP.Models.DAO;
using FiltronASP.Models.DAO.Extensions;
using FiltronASP.Models.DAO.Interfaces;
using FiltronASP.Models;
using FiltronASP.Logger;

namespace FiltronASP.Areas.Admin.Controllers
{
    /// <summary>
    /// Bazowa klasa dla wszystkich kontrolerow, zawierajaca metody pobierajace standardowe dane, np. do menu.
    /// </summary>
    [HandleErrorWithMyLogger]
    public class BaseController : Controller
    {
        /// <summary>
        /// klasa odpowiedzialna za operacja na bazie danych, tabela wersji jezykowych
        /// </summary>
        protected ILanguageDAO _languageDAO;

        /// <summary>
        /// klasa odpowiedzialna za operacja na bazie danych, tabela grup stron
        /// </summary>
        protected IPageTypeDAO _pageTypeDAO;

        /// <summary>
        /// klasa odpowiedzialna za operacja na bazie danych, tabela menu
        /// </summary>
        protected IMenuDAO _menuDAO;

        /// <summary>
        /// klasa odpowiedzialna za operacja na bazie danych, tabela uzytkownikow
        /// </summary>
        protected IUserDAO _userDAO;

        /// <summary>
        /// Konstruktor (dependency injection).
        /// </summary>
        public BaseController()
            : this(new LanguageDAO(), new PageTypeDAO(), new MenuDAO(), new UserDAO())
        {
        }

        /// <summary>
        /// Konstruktor.
        /// </summary>
        /// <param name="languageDAO">klasa odpowiedzialna za operacja na bazie danych, tabela wersji jezykowych</param>
        /// <param name="pageTypeDAO">klasa odpowiedzialna za operacja na bazie danych, tabela grup stron</param>
        /// <param name="menuDAO">klasa odpowiedzialna za operacja na bazie danych, tabela menu</param>
        public BaseController(ILanguageDAO languageDAO, IPageTypeDAO pageTypeDAO, IMenuDAO menuDAO, IUserDAO userDAO)
        {
            this._languageDAO = languageDAO;
            this._pageTypeDAO = pageTypeDAO;
            this._menuDAO = menuDAO;
            this._userDAO = userDAO;
        }

        /// <summary>
        /// Metoda pomocnicza do pobierania modelu <code>PagesIndexViewModel</code>.
        /// </summary>
        /// <param name="page">biezaca strona paginacji</param>
        /// <param name="pageTypeId">id biezacej grupy stron</param>
        /// <returns>odpowiedni model danych</returns>
        protected BaseViewModel GetBaseViewModel(int? currentLanguageId)
        {
            return new BaseViewModel(this.GetLanguagesToDropDown(currentLanguageId),
                        this.GetPageTypesInMenu(currentLanguageId), this.GetMenus(currentLanguageId),
                        this.GetCurrentLanguage(currentLanguageId));
        }

        /// <summary>
        /// Metoda pobieraja wersje jezykowe umieszczane w drop downie na gorze strony.
        /// </summary>
        /// <param name="selectedId">aktualnie wybrana wersja jezykowa</param>
        /// <returns>wersje jezykowe umieszczane w drop downie</returns>
        protected IQueryable<Language> GetLanguagesToDropDown(int? selectedId)
        {
            try
            {
                return this.GetLanguagesToDropDown(selectedId, this.GetAuthenticatedUserId());
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
            }   //catch
            return null;
        }

        /// <summary>
        /// Metoda pobieraja wersje jezykowe umieszczane w drop downie na gorze strony.
        /// </summary>
        /// <param name="selectedId">aktualnie wybrana wersja jezykowa</param>
        /// <returns>wersje jezykowe umieszczane w drop downie</returns>
        protected IQueryable<Language> GetLanguagesToDropDown(int? selectedId, int? userId)
        {
            if (this._languageDAO == null)
            {
                return null;
            }   //if null
            return this._languageDAO.FindAcceptableByUserId(userId);
        }

        /// <summary>
        /// Metoda pobieraja grupy stron umieszczane w bocznym menu.
        /// </summary>
        /// <param name="currentLanguageId">aktualnie wybrana wersja jezykowa</param>
        /// <returns>grupy stron umieszczane w bocznym menu</returns>
        protected IQueryable<PageType> GetPageTypesInMenu(int? currentLanguageId)
        {
            if (this._pageTypeDAO == null)
            {
                return null;
            }   //if null
            if (currentLanguageId.HasValue)
            {
                return this._pageTypeDAO.FindByLanguage(currentLanguageId.Value);
            }   //if value
            return null;
        }

        /// <summary>
        /// Metoda pobierajaca listę menu w bocznym menu.
        /// </summary>
        /// <param name="currentLanguageId">aktualnie wybrana wersja jezykowa</param>
        /// <returns>lista menu w bocznym menu</returns>
        protected IQueryable<Menu> GetMenus(int? currentLanguageId)
        {
            if (this._menuDAO == null)
            {
                return null;
            }   //if null
            if (currentLanguageId.HasValue)
            {
                return this._menuDAO.FindByLanguageId(currentLanguageId.Value);
            }   //if value
            return null;
        }

        /// <summary>
        /// Metoda pobierajaca aktualna wersje jezykowa.
        /// </summary>
        /// <param name="languageId">id aktualnej wersji jezykowej</param>
        /// <returns>aktualna wersja jezykowa</returns>
        protected Language GetCurrentLanguage(int? languageId)
        {
            if (!languageId.HasValue)
            {
                return null;
            }   //if
            return this._languageDAO.FindByPK(languageId);
        }

        /// <summary>
        /// Pobieranie id aktualnie zalogowanego uzytkownika.
        /// </summary>
        /// <returns>id zalogowanego uzytkownika</returns>
        protected int? GetAuthenticatedUserId()
        {
            try
            {
                if (Request != null)
                {
                    if (Request.IsAuthenticated)
                    {
                        if (User != null)
                        {
                            FiltronASP.Models.User user = this._userDAO.FindByUserLogin(User.Identity.Name);
                            if (user != null)
                            {
                                return user.user_id;
                            }   //if
                        }   //if
                    }   //if
                }   //if
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
            }   //catch
            return null;
        }

        protected ActionResult GetAccessDeniedView()
        {
            return RedirectToAction("AccessDenied", "Users");
        }

    }
}
